Source: Reporter.js

/**
 * Created by 212556710 on 4/28/16.
 */
module.exports = function JsonOutputHook() {
    var Cucumber = require('cucumber');
    var logger = require('./Logger.js');
    var Promise = require('bluebird');
    //var RallyHelper = require('./RallyHelper.js');
    var JsonFormatter = Cucumber.Listener.JsonFormatter();
    var json_rally = '';
    var cucumber_json = '';
    var fs = require('fs');
    var dir = './Reports/json_report';
    if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir);
    }
    var special_char_tf = false;//add special char check
    var special_char_tc = false;
    var special_char_step = false;
    var wroteFile = false;
    var eof = false;
    var imageCount = 0;
    this.registerListener(JsonFormatter);
    JsonFormatter.log = function (jsonold, callback) {

        // Loops through the provided array to check if the test case has arguements
        var checkarray = function (array, str_to_check) {
            var num_times = 0;
            for (var temp = 0; temp < array.length; temp++) {
                if (array[temp] == str_to_check) {
                    num_times++;
                    has_arg = true;
                }
                if (temp == array.length - 1)
                    return (num_times);
            }
        }

        var RallyJson = JSON.parse(jsonold);
        var has_arg = false;
        var duplicate_arg = false;

        // For loop to go through all the feature files
        for (var feature = 0; feature < RallyJson.length; feature++) {

            var feature_name = RallyJson[feature].name;
            var args = [];
            // var re = /\(|\)/;
            // var TFchars = re.test(feature_name);

            // if (TFchars) {
            //     special_char_tf = true;
            //     console.log('Error in Feature Name');
            //     logger.info('Error in Feature Name');
            //     break;
            // }
            // else {
            //     special_char_tf = false;
            // }
            for (var scenario = 0; scenario < RallyJson[feature].elements.length; scenario++) {
                var scenario_name = RallyJson[feature].elements[scenario].name;
                // var TCspecial_chars = /\(|\)/;
                // var check_chars = TCspecial_chars.test(scenario_name);
                // if (check_chars) {
                //     special_char_tc = true;
                //     console.log('Error in Scenario Name');
                //     logger.info('Error in Scenario Name');
                //     break;
                // } else {
                //     special_char_tc = false;
                // }

                // This variable is going to hold the array of user stories
                var arrUserStory = "";
                var testCaseNumber = "";
                var testcaseName = "";

                //read user story from env file
                if (process.env.user_story != undefined && process.env.user_story != "") {
                    arrUserStory = process.env.user_story;
                    arrUserStory = arrUserStory.match(/US[0-9]+/g);
                }

                //read user story from feature file
                var checkUserStory = scenario_name.split(":");
                if (process.env.overwrite_US == "false" || process.env.overwrite_US == undefined) {

                    if (checkUserStory.length == 2) {
                        if (checkUserStory[0].match(/US[0-9]+/g)) {
                            arrUserStory = checkUserStory[0];
                            arrUserStory = arrUserStory.match(/US[0-9]+/g);
                        }
                        else {
                            testCaseNumber = checkUserStory[0];
                        }
                        testcaseName = checkUserStory[1]
                    }
                    // Checking to see if TC number is defined here. Then grabs the right index for the split array to get the user story
                    else if (checkUserStory.length == 3) {
                        if (checkUserStory[0].match(/US[0-9]+/)) {
                            arrUserStory = checkUserStory[0];
                            testCaseNumber = checkUserStory[1]
                        }
                        else {
                            testCaseNumber = checkUserStory[0]
                            arrUserStory = checkUserStory[1];
                        }
                        arrUserStory = arrUserStory.match(/US[0-9]+/g);
                        testcaseName = checkUserStory[2]
                    }
                    else {
                        testcaseName = checkUserStory[0]
                    }
                }

                // If env overwrite US is set to true but we still need to get the test case number if there is one
                else {
                    if (checkUserStory.length == 2) {
                        if (!checkUserStory[0].match(/US[0-9]+/g)) {
                            testCaseNumber = checkUserStory[0];
                        }
                        testcaseName = checkUserStory[1]
                    }
                    // Checking to see if TC number is defined here. Then grabs the right index for the split array to get the user story
                    else if (checkUserStory.length == 3) {
                        if (checkUserStory[0].match(/US[0-9]+/)) {
                            testCaseNumber = checkUserStory[1]
                        }
                        else {
                            testCaseNumber = checkUserStory[0]
                        }
                        testcaseName = checkUserStory[2]
                    }
                    else {
                        testcaseName = checkUserStory[0]
                    }
                }


                // This is to replace the scenario name with the correct userstory whether it got it from the env or feature file

                if (arrUserStory != "")
                    var userStoryString = arrUserStory.join(",");

                if (testCaseNumber != "") {
                    if (userStoryString == undefined && testCaseNumber != undefined) {
                        userStoryString = testCaseNumber;
                    }
                    else {
                        userStoryString += ":" + testCaseNumber;
                    }
                }

                if (checkUserStory.length > 1 && (process.env.overwrite_US == "false" || process.env.overwrite_US == undefined)) {
                    RallyJson[feature].elements[scenario].name = userStoryString + ":" + testcaseName;;
                } else if (userStoryString != "" && userStoryString!=undefined) {
                    RallyJson[feature].elements[scenario].name = userStoryString+":"+testcaseName;
                }
                else {
                    RallyJson[feature].elements[scenario].name = checkUserStory[0];
                }
                //if there are multiple user story.
                if (arrUserStory != null && arrUserStory.length > 1) {
                    var name = RallyJson[feature].elements[scenario].name;
                    RallyJson[feature].elements[scenario].name = checkUserStory[0].replace(/(,(\s*)?US[0-9]+)+/g, "") + ":" + checkUserStory[1] + "_US_1";
                    scenario_name = RallyJson[feature].elements[scenario].name;
                    for (var i = 1; i < arrUserStory.length; i++) {
                        var temp_element = JSON.parse(JSON.stringify(RallyJson[feature].elements[scenario]));
                        var temp_element_userstory = temp_element.name.split(":")[0].replace(/US[0-9]+/g, arrUserStory[i])
                        temp_element.name = temp_element_userstory + ":" + temp_element.name.split(":")[1].substring(0, temp_element.name.split(":")[1].length - 2) + "_" + (i + 1);
                        RallyJson[feature].elements.push(temp_element);
                    }
                }


                for (var step = 0; step < RallyJson[feature].elements[scenario].steps.length; step++) {
                    if (RallyJson[feature].elements[scenario].steps[step].name != undefined) {
                        var name = RallyJson[feature].elements[scenario].steps[step].name;
                        // var stepSPChar = /\(|\)/;
                        // var check_StepChars = stepSPChar.test(name);
                        // if (check_StepChars) {
                        //     special_char_step = true;
                        //     console.log('Error in step declaration');
                        //     logger.info('Error in step declaration');
                        //     break;
                        // } else {
                        //     special_char_step = false;
                        // }
                        var reg_exp = new RegExp('\".+?\"');
                        var arg = reg_exp.exec(name);
                        if (arg != undefined) {
                            has_arg = true;
                            if (args.length > 0) {
                                var retrned = checkarray(args, arg[0]);
                                if (retrned > 0) {
                                    duplicate_arg = true;
                                    RallyJson[feature].elements[scenario].name = scenario_name + ' ' + arg[0] + ' ' + retrned;
                                    RallyJson[feature].elements[scenario].name = RallyJson[feature].elements[scenario].name.split('"').join('');

                                } else {
                                    RallyJson[feature].elements[scenario].name = scenario_name + ' ' + arg[0];
                                    RallyJson[feature].elements[scenario].name = RallyJson[feature].elements[scenario].name.split('"').join('');

                                }
                            }
                            args.push(arg[0]);
                        } else if (step == RallyJson[feature].elements[scenario].steps.length - 2) {
                            has_arg = false;
                            break;
                        }
                    } else if (step == RallyJson[feature].elements[scenario].steps.length - 2) {
                        has_arg = false;
                        break;
                    }
                }
                if (special_char_step)
                    break;
                if ((scenario == RallyJson[feature].elements.length - 1) && (feature == RallyJson.length - 1)) {
                    json_rally = JSON.stringify(RallyJson, null, "\t");
                    cucumber_json = jsonold;
                }
            }
            if (special_char_tc || special_char_step || wroteFile) {
                break;
            }
        }
    };

    this.After(function (scenario, callback) {
        console.log('after scenario');
        if (scenario.isFailed()) {
            Logger.info("Results: Failed");
            browser.takeScreenshot().then(function (png) {
                imageCount += 1;
                var decodedImage = new Buffer(png, "base64").toString("binary");
                fs.writeFile("Reports/image" + imageCount + ".png", decodedImage, 'binary', function (err) {
                    scenario.attach(decodedImage, "image/png");
                    console.log("Attached");
                    callback()
                })
            });
        } else {
            Logger.info("Results: Passed");
            callback();
        }
    });

    this.registerHandler('BeforeScenario', function (event, callback) {
        var scenario = event.getPayloadItem('scenario');
        Logger.info("|--------------------------------------------------------|");
        Logger.info("Test " + scenario.getName() + " has started");
        Logger.info("|--------------------------------------------------------|\r\n");
        callback();
    });

    this.registerHandler('AfterScenario', function (event, callback) {
        var scenario = event.getPayloadItem('scenario');
        Logger.info("|--------------------------------------------------------|");
        Logger.info("Test " + scenario.getName() + " has ended");
        Logger.info("|--------------------------------------------------------|\r\n\r\n");
        callback();
    });

    this.registerHandler('AfterFeatures', function (features, callback) {
        if (json_rally == '') {
            //spin for loop until json rally finished
            var date = new Date();
            while (new Date() - date < 1500) {
                //spin for 1.5 sec
            }
        }
        fs.writeFile('Reports/json_report/rally.json', json_rally, function (err) {
            if (err) console.log(err);
            else {
                //fs.writeFile('Reports/json_report/cucumber.json', cucumber_json, function (err) {
                //     if (err) console.log(err);
                var Rally = require('./Rally.js');
                if ((!special_char_tf) && (!special_char_tc) && (!special_char_step)) {
                    Rally.RallyWebAPI('../../../Reports/json_report/rally.json', function () {
                        wroteFile = true;
                        callback();
                    });
                } else {
                    console.log('The following characters are not supported in postToRally:' +
                        ' "(" and ")" - please check your feature file');
                    logger.info('The following characters are not supported in postToRally:' +
                        ' "(" and ")" - please check your feature file');
                    callback();
                }
                //});
            }
        });
    });
};